package cn.nawang.ebeim.client.transfer;

import java.io.File;
import java.net.URI;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.nawang.ebeim.client.util.FileUtil;
import cn.nawang.ebeim.common.entity.FileInfo;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultHttpRequest;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpRequestEncoder;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseDecoder;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.QueryStringEncoder;
import io.netty.handler.stream.ChunkedWriteHandler;

public class HttpUploadQueryClient {
  private static final Logger LOG =
      LoggerFactory.getLogger(HttpUploadQueryClientInboundHandler.class);
  private String host;
  private int port;
  private FileInfo info;
  private static final int connLine = 1;
  private boolean connect;
  private int flag;

  private static volatile long CHANNEL_NUM = 0 ;
  private final static long MAX_CHANNEL_NUM = 10 ;

  public HttpUploadQueryClient(String host, int port) {
    this.host = host;
    this.port = port;
    if (CHANNEL_NUM >= MAX_CHANNEL_NUM){
      throw new RuntimeException("连接数超过限制,请稍后重试!");
    }else {
      CHANNEL_NUM ++ ;
    }
  }

  public void run(final FileInfo info) throws Exception {
    this.info = info;
    EventLoopGroup group = new NioEventLoopGroup(connLine);
    try {
      Bootstrap b = new Bootstrap();
      b.group(group).channel(NioSocketChannel.class);
      b.handler(new ChannelInitializer<SocketChannel>() {
        @Override
        protected void initChannel(SocketChannel ch) throws Exception {
          ChannelPipeline pipeline = ch.pipeline();
          pipeline.addLast("decoder", new HttpResponseDecoder());
          pipeline.addLast("encoder", new HttpRequestEncoder());
          pipeline.addLast("http-encoder", new ChunkedWriteHandler());
          pipeline.addLast("dispatcher", new HttpUploadQueryClientInboundHandler());
        }
      });
      ChannelFuture f = b.connect(host, port).sync();
      f.channel().closeFuture().sync();
    } finally {
      LOG.info("-------退出----------");
      group.shutdownGracefully();
      CHANNEL_NUM -- ;
      if (!connect||flag==0) {
        throw new Exception("网络信号差，未建立连接！文件(" + info.getPath() + ")连接不到[" + host + ":" + port + "]-----");
      }
      else if (flag!=3) {
        throw new Exception("文件(" + info.getPath() + ")传输到[" + host + ":" + port + "]失败");
      }

    }
  }

  private class HttpUploadQueryClientInboundHandler
      extends SimpleChannelInboundHandler<HttpObject> {
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
      connect = true;
      File f = new File(info.getPath());
      QueryStringEncoder encoder = new QueryStringEncoder("query");
      encoder.addParam("type", String.valueOf(info.getType()));
      encoder.addParam("version", info.getVersion());
      encoder.addParam("dataId", info.getDataId());
      encoder.addParam("signature", info.getSignature());
      URI uriGet = new URI(encoder.toString());
      final HttpRequest request =
          new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uriGet.toASCIIString());
      HttpHeaders.setContentLength(request, f.length());
      ctx.writeAndFlush(request);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
      cause.printStackTrace();
      ctx.close();
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
      if (msg instanceof HttpResponse) {
        HttpResponse response = (HttpResponse) msg;
        long uploadLength = response.headers().getContentLength(response);
        LOG.info("STATUS: " + response.getStatus());
        // 上传文件
        String md5=FileUtil.getFileHd5(info.getPath());
        HttpUploadClient upload = new HttpUploadClient(host, port);
         flag = upload.run(info, uploadLength,md5);
      }
      if (msg instanceof HttpContent) {

      }
    }
  }
}


